package org.jugile.restapi.domain;


import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Comparator;
import java.util.List;
import java.util.ArrayList;
import java.util.Date;
import java.util.Set;

import org.apache.log4j.Logger;
import org.jugile.util.*;


import org.jugile.restapi.common.*;

public class PathItemCollection extends CollectionBase implements java.lang.Iterable<PathItem> {
	static Logger log = Logger.getLogger(PathItemCollection.class);
	
	private Bos<PathItem> items;
	
	public PathItemCollection() {
		items = new Bos<PathItem>();
	}
	public PathItemCollection(Bos<PathItem> lst) {
		if (lst == null) items = new Bos<PathItem>();
		else items = lst.clone();
	}
	public PathItemCollection(List<PathItem> list) {
		items = new Bos<PathItem>();		
		items.add(list);
	}
	
	public void add(List<String> ids) {
		if (ids != null) {
			items = new Bos<PathItem>();		
			Domain d = Domain.getDomain();
			for (String id : ids) add(d.getPathItem(id));
		}		
	}

	public boolean contains(PathItem o) { return items.contains(o);	}
	public void add(PathItem o) { items.add(o);	}
	public void remove(PathItem o) { items.remove(o); }
	public PathItemCollection clone() { return new PathItemCollection(items.clone()); }
	public int size() { filter(); return items.size(); }
	public Set<Long> getKeys() { return items.getKeys(); }
	
	private Query q = null;
	private Query q() {
		if (q == null) q = new Query();
		return q;
	}
	private void filter() {
		if (q != null) items = items.query(q);
		q = null;
	}
	
	// ---- operations -----
	public PathItemCollection and(PathItemCollection c) { items.and(c.items); return this; }
	public PathItemCollection not(PathItemCollection c) { items.not(c.items); return this; }
	public PathItemCollection xor(PathItemCollection c) { items.xor(c.items); return this; }
	public PathItemCollection or(PathItemCollection c) { items.or(c.items); return this; }
	public PathItemCollection keep(String mname) { items.keep(mname); return this; }
	public PathItemCollection not(String mname) { items.not(mname); return this; }


	// ---- attribute finders ----
	public PathItemCollection byName(String v) { q().and("==", "name", v); return this; }
	public PathItemCollection byName(String op, String v) { q().and(op, "name", v); return this; }
	public PathItemCollection byDesc(String v) { q().and("==", "desc", v); return this; }
	public PathItemCollection byDesc(String op, String v) { q().and(op, "desc", v); return this; }
	public PathItemCollection byStr(String v) { q().and("==", "str", v); return this; }
	public PathItemCollection byStr(String op, String v) { q().and(op, "str", v); return this; }
	public PathItemCollection byRegexp(String v) { q().and("==", "regexp", v); return this; }
	public PathItemCollection byRegexp(String op, String v) { q().and(op, "regexp", v); return this; }
	public PathItemCollection byTmplDir(String v) { q().and("==", "tmplDir", v); return this; }
	public PathItemCollection byTmplDir(String op, String v) { q().and(op, "tmplDir", v); return this; }
	public PathItemCollection byModelDir(String v) { q().and("==", "modelDir", v); return this; }
	public PathItemCollection byModelDir(String op, String v) { q().and(op, "modelDir", v); return this; }
	public PathItemCollection byPkg(String v) { q().and("==", "pkg", v); return this; }
	public PathItemCollection byPkg(String op, String v) { q().and(op, "pkg", v); return this; }
	public PathItemCollection byController(String v) { q().and("==", "controller", v); return this; }
	public PathItemCollection byController(String op, String v) { q().and(op, "controller", v); return this; }
	public PathItemCollection byDcontroller(String v) { q().and("==", "dcontroller", v); return this; }
	public PathItemCollection byDcontroller(String op, String v) { q().and(op, "dcontroller", v); return this; }
	public PathItemCollection byRedirect(String v) { q().and("==", "redirect", v); return this; }
	public PathItemCollection byRedirect(String op, String v) { q().and(op, "redirect", v); return this; }
	public PathItemCollection byVar(String v) { q().and("==", "var", v); return this; }
	public PathItemCollection byVar(String op, String v) { q().and(op, "var", v); return this; }
	public PathItemCollection byBorder(String v) { q().and("==", "border", v); return this; }
	public PathItemCollection byBorder(String op, String v) { q().and(op, "border", v); return this; }
	public PathItemCollection byType(PathItemType v) { q().and("==", "type", v); return this; }
	public PathItemCollection byType(String op, PathItemType v) { q().and(op, "type", v); return this; }
	public PathItemCollection byCondition(String v) { q().and("==", "condition", v); return this; }
	public PathItemCollection byCondition(String op, String v) { q().and(op, "condition", v); return this; }
 

	// ---- filtering finders ----
	public PathItemCollection byMatchName(String name) {
		Bos<PathItem> res = new Bos<PathItem>();
		for (PathItem o : items) if (o.isMatchName(name)) res.add(o);
		items = res;
		return this;		
	}	
	
 

	// ---- utility services ----
	public Bos<PathItem> getItems() { filter(); return items; }
	public List<PathItem> list() { filter();	return items.sort("id"); }
	public Iterator<PathItem> iterator() { filter();	return items.iterator(); }

	
	// --- selfref ---
	public PathItemCollection byParent(PathItem v) { q().and("==", "parent", v); return this; }
 
	// --- n - 1 ----
	public PathItemCollection byApi(Api v) { q().and("==", "Api", v); return this; }
 

	public List<PathItem> page(int page, int size, String sortcriteria) {
		filter();
		return items.page(page, size, sortcriteria);
	}

	public List<PathItem> sublist(int start, int end, String sortcriteria) {
		filter();
		return items.sublist(start, end, sortcriteria);
	}

	
	public List<PathItem> sort(String fld) { filter(); return items.sort(fld); }
	public PathItem next() { filter(); return iterator().next(); }
	public boolean hasNext() { filter(); return iterator().hasNext(); }
	public PathItem unique() { 
		Query q2 = q;
		if (size() > 1) {
			String querystr = "";
			try {
				if (q2 != null) querystr = q2.toString();
			} catch (Exception e) {}
			//Jugile.fail("Not unique PathItem : " + size() + " q: "+querystr);
			log.error("Not unique PathItem : " + size() + " q: "+querystr);
			return first("id");
		}
		if(!hasNext()) return null; 
		return next(); 
	}
	
	public List<PathItem> first(int count) { return first(count,"id");} 
	public List<PathItem> first(int count, String sort) {
		List<PathItem> res = sort(sort);
		if (count > res.size()) count = res.size();
		return res.subList(0, count);
	}
	public PathItem first(String sort) { 
		List<PathItem> res = first(1,sort);
		if (res.size() > 0) return res.get(0);
		return null;
	}
	
	public void add(PathItemCollection c) {
		items.add(c.items);
	}
	


}